# -*- encoding: utf-8 -*-

module Faye
  class PersistentRedis < Faye::Redis
    DEFAULT_EXPIRE = 60 # default expiration timeout for awaiting messages

    def subscribe(client_id, channel, &callback)
      super
      publish_awaiting_messages(channel)
    end

    def publish_awaiting_messages(channel)
      # fetch awaiting messages from redis and publish them
      @redis.lpop(@ns + "/channels#{channel}/awaiting_messages") do |json_message|
        if json_message
          message = Oj.load(json_message)
          publish(message, [message["channel"]], json_message)
          publish_awaiting_messages(channel)
        end
      end
    end

    def publish(message, channels, json_message = nil)
      init
      @server.debug 'Publishing message ?', message

      json_message ||= Oj.dump(message)
      channels = Channel.expand(message['channel'])
      keys = channels.map { |c| @ns + "/channels#{c}" }

      @redis.sunion(*keys) do |clients|
        if clients.empty?
          key = @ns + "/channels#{message["channel"]}/awaiting_messages"
          # Store message in redis
          @redis.rpush(key, json_message)
          # Set expiration time to one minute
          @redis.expire(key, @options[:expire] || DEFAULT_EXPIRE)
        else
          clients.each do |client_id|
            @server.debug 'Queueing for client ?: ?', client_id, message
            @redis.rpush(@ns + "/clients/#{client_id}/messages", json_message)
            @redis.publish(@ns + '/notifications', client_id)
          end
        end
      end

      @server.trigger(:publish, message['clientId'], message['channel'], message['data'])
    end
  end
end